package com.rj.util;

import com.rj.core.tree.TreeEntity;
import com.rj.core.tree.TreeSelect;
import com.rj.core.tree.TreeStructMap;
import lombok.Data;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 树构建工具
 *
 * @author YFZX_RANLUBO
 */
public class TreeUtils {
    /**
     * 获取下拉树结构(通过实体parentId确定根节点)
     *
     * @param entities
     * @param structMap
     * @param <E>
     * @return
     */
    public static <E> List<TreeSelect> buildTreeSelect(List<E> entities, TreeStructMap<E> structMap) {
        return buildTreeSelect(null, entities, structMap);
    }

    /**
     * 获取下拉树结构
     *
     * @param rootId    根节点
     * @param entities  节点信息
     * @param structMap 转换器
     * @param <E>
     * @return List<TreeEntity>
     */
    public static <E> List<TreeSelect> buildTreeSelect(Long rootId, List<E> entities, TreeStructMap<E> structMap) {
        List<TreeEntity> trees = buildTree(rootId, entities, structMap);
        return trees.stream().map(TreeSelect::new).collect(Collectors.toList());
    }

    /**
     * 获取结构树(通过实体parentId确定根节点)
     *
     * @param entities  节点信息
     * @param structMap 转换器
     * @param <E>
     * @return List<TreeEntity>
     */
    public static <E> List<TreeEntity> buildTree(List<E> entities, TreeStructMap<E> structMap) {
        return buildTree(null, entities, structMap);
    }

    /**
     * 从中间查找
     *
     * @param entities  节点信息
     * @param structMap 转换器
     * @param <E>
     * @return List<TreeEntity>
     */
    public static <E> List<TreeEntity> buildTreeMiddle(Long middleId, List<E> entities, TreeStructMap<E> structMap) {
        List<TreeEntity> all = entities.stream().map(structMap::convert).collect(Collectors.toList());
        List<TreeEntity> middles = all.stream().filter(e -> e.getId().equals(middleId)).collect(Collectors.toList());
        List<TreeEntity> real = new ArrayList<>();
        if (middles.isEmpty()) {
            throw new RuntimeException("middleId not exists");
        }
        TreeEntity middle = middles.get(0);
        //left
        real.add(0, middle);
        left(real, all);
        //right
        right(middle, all);
        return real;
    }

    public static void left(List<TreeEntity> parents, List<TreeEntity> all) {
        TreeEntity parent = parents.get(0);
        Long parentId = parent.getParentId();
        for (TreeEntity e : all) {
            if (parentId.equals(e.getId())) {
                e.getChildren().add(parent);
                parents.remove(0);
                parents.add(e);
                left(parents, all);
            }
        }
    }

    public static void right(TreeEntity middle, List<TreeEntity> all) {
        Long id = middle.getId();
        for (TreeEntity e : all) {
            if (id.equals(e.getParentId())) {
                middle.getChildren().add(e);
                right(e, all);
            }
        }
    }

    /**
     * 获取结构树
     *
     * @param rootId    根节点
     * @param entities  节点信息
     * @param structMap 转换器
     * @param <E>
     * @return List<TreeEntity>
     */
    public static <E> List<TreeEntity> buildTree(Long rootId, List<E> entities, TreeStructMap<E> structMap) {
        //转换为树实体对象
        List<TreeEntity> all = entities.stream().map(structMap::convert).collect(Collectors.toList());
        List<TreeEntity> real = new ArrayList<>();
        List<Long> tmp = new ArrayList<>();
        //取到所有节点ID
        all.forEach(e -> {
            tmp.add(e.getId());
        });
        //1.找到根节点
        //2.通过根节点查找子节点
        boolean hasRoot = (rootId != null);
        if (hasRoot) {
            all.forEach(e -> {
                if (rootId.equals(e.getId())) {
                    real.add(e);
                    buildChildren(e, all);
                }
            });
        } else {
            all.forEach(e -> {
                boolean isRoot = !tmp.contains(e.getParentId());
                if (isRoot) {
                    real.add(e);
                    buildChildren(e, all);
                }
            });
        }

        if (real.isEmpty()) {
            throw new RuntimeException("buildTree not rootNode");
        }
        return real;
    }

    /***
     * 绑定子元素
     * @param parent
     * @param all
     * @return
     */
    public static TreeEntity buildChildren(TreeEntity parent, List<TreeEntity> all) {
        for (TreeEntity c : all) {
            boolean isChild = parent.getId().equals(c.getParentId());
            if (isChild) {
                //找到子元素
                parent.getChildren().add(c);
                //绑定子子元素
                buildChildren(c, all);
            }
        }
        return parent;

    }

    public static void build(Integer id, Integer parent, List<Tree> trees) {
        Tree tree = new Tree();
        tree.setId(id.longValue());
        tree.setParent(parent == null ? null : parent.longValue());
        trees.add(tree);
    }

    @Data
    static class Tree {
        private Long id;
        private Long parent;

    }
}